<template>
  <div class="content">
    <el-upload
      ref="fileUpload"
      :http-request="manualUpload"
      :before-remove="beforeRemove"
      :on-success="handleSuccess"
      :on-remove="handleRemove"
      :on-exceed="handleExceed"
      :drag="listType!=='picture-card'"
      :accept="accept"
      :multiple="limit > 1"
      :limit="limit===1?2:limit"
      :file-list="fileList"
      :list-type="listType"
      action=""
    >

      <i v-if="listType==='picture-card'" class="el-icon-plus"/>

      <i v-if="listType!=='picture-card'" class="el-icon-upload" />
      <div v-if="listType!=='picture-card'" class="el-upload__text">
        将文件拖到此处，或
        <em>点击上传</em>
      </div>
      <div v-if="tips" slot="tip" class="el-upload__tip">{{ tips }}</div>
    </el-upload>
  </div>
</template>

<script>
import { buildDir } from '@/utils/file-utils'
import { fetchToken } from '@/api/sys/config/cos'
import COS from 'cos-js-sdk-v5'
import { compressImage } from '@/utils/upload'

export default {
  name: 'FileUploadCos',
  props: {
    value: {
      type: Array,
      default() {
        return []
      }
    },
    accept: String,
    tips: String,
    listType: String,

    limit: {
      type: Number,
      default: 1
    },
    compress: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      fileList: [],
      fileNames: {},
      cos: null,
      taskId: '',
      conf: { }
    }
  },
  watch: {
    // 检测查询变化
    value: {
      handler(val) {
        this.fileList = val
      }
    }
  },

  mounted() {
    this.fetchConfig()
  },

  created() {
    this.fillValue()
  },
  methods: {

    // 填充数据
    fillValue() {
      this.fileList = this.value
    },

    // 文件上传成功时的钩子
    handleSuccess(response, file, fileList) {
      // 只能传一个的进行替换
      if (this.limit === 1 && fileList.length>1) {
        const url = this.conf.url + this.fileNames[file.uid]
        // 反转并保留一个
        fileList = [{ url: url, name: url }]
      } else {
        // 上传成功替换服务端URL
        for (let i = 0; i< fileList.length; i++) {
          if (file.uid === fileList[i].uid) {
            fileList[i].url = this.conf.url + this.fileNames[file.uid]
          }
        }
      }

      this.$emit('input', fileList)
    },

    beforeUpload(file) {
      this.$emit('select', file.name)
      return compressImage(file, this.compress)
    },

    // 获取基础配置
    fetchConfig() {
      // 获得上传令牌
      fetchToken().then(res => {
        this.conf = res.data
        // 使用临时秘钥初始化上传对象
        this.cos = new COS({
          SecretId: res.data.tmpSecretId,
          SecretKey: res.data.tmpSecretKey,
          XCosSecurityToken: res.data.sessionToken
        })
      }).catch(err => {
        this.$message.error(`获取COS上传令牌失败： ${err} `)
      })
    },

    // 文件超出个数限制时的钩子
    handleExceed() {
      this.$message.warning(`每次只能上传 ${this.limit} 个文件`)
    },
    // 删除文件之前的钩子
    beforeRemove() {
      return this.$confirm(`确定移除文件吗？`)
    },
    // 文件列表移除文件时的钩子
    handleRemove(file) {
      // 移除文件
      for (let i = 0; i<this.fileList.length; i++) {
        if (file.uid === this.fileList[i].uid) {
          this.fileList.splice(i, 1)
        }
      }

      // 取消进行中的任务
      this.cos.cancelTask(this.taskId)

      // 同步数据
      this.$emit('input', this.fileList)
    },

    // 手动上传文件
    manualUpload(param) {
      const file = param.file
      const key = this.buildName(file)
      const that = this

      this.fileNames[file.uid] = key

      this.cos.sliceUploadFile({
        Bucket: that.conf.bucket,
        Region: that.conf.region,
        Key: key,
        StorageClass: 'STANDARD',
        Body: file,
        onTaskReady: function(taskId) {
          that.taskId = taskId
        },
        onProgress: function(progressData) {
          // 文件进度条
          const progress = progressData.percent
          const percent = progress * 100
          param.onProgress({ percent: percent })
        }

      }, function() {
        // 成功回调
        param.onSuccess()
      })
    },

    // 重命名文件
    buildName(file) {
      const temporary = file.name.lastIndexOf('.')
      const fileNameLength = file.name.length
      const fileFormat = file.name.substring(
        temporary + 1,
        fileNameLength
      )
      return buildDir() + '.' + fileFormat
    }
  }
}
</script>
